package com.nacl.upload.service;

import cn.hutool.core.thread.ThreadUtil;
import com.google.common.cache.LoadingCache;
import com.nacl.upload.po.UploadTask;
import com.nacl.upload.po.enums.enums.StorageChannel;
import com.nacl.upload.util.SnowflakeIdGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.function.BiConsumer;

/**
 * @description: 异步处理文件生成任务
 * @author: xukang
 * @create: 2025-08-01
 */
@Service
public class AsyncUploadService {
    @Autowired
    @Qualifier("uploadCache")
    private LoadingCache<Long, UploadTask> uploadCache;
    @Value("${upload.storageChannel}")
    private String storageChannel;


    /**
     * @description: 异步处理文件生成任务
     * @author: xukang
     * @create: 2025/8/5
     */
    public UploadTask upload(MultipartFile file, Long userId, BiConsumer<MultipartFile, UploadTask> processFile) {
        String originalFileName = file.getOriginalFilename();

        // 创建任务记录
        UploadTask task = new UploadTask();

        task.setFileName(originalFileName);
        task.setFileSize(file.getSize());
        task.setContentType(file.getContentType());
        task.setUploadTime(new Date());
        // 处理中
        task.setStatus(UploadTask.TaskStatus.PROCESSING);
        task.setUserId(userId);
        // task.setFilePath(filePath);

        // 保存任务记录
        storageSave(task);

        // hutool快捷线程池 异步处理
        ThreadUtil.execute(
                () -> {
                    try {
                        processFile.accept(file, task.clone());
                    } catch (CloneNotSupportedException e) {
                        throw new RuntimeException(e);
                    }
                }
        );

        return task;
    }

    /**
     * @description: 获取单个上传结果，注意有效期
     * @author: xukang
     * @create: 2025/8/5
     */
    public UploadTask getTaskStatus(Long taskId) {
        try {
            UploadTask uploadTask = uploadCache.get(taskId);
            if (uploadTask.getId() == null) {
                return null;
            } else {
                return uploadTask;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * @description: 获取某用户所有的上传任务，注意有效期
     * @author: xukang
     * @create: 2025/8/5
     */
    public List<UploadTask> getUserTasks(Long userId) {
        Map<Long, UploadTask> cacheMap = uploadCache.asMap();
        if (cacheMap.isEmpty()) {
            return Arrays.asList();
        } else {
            List<UploadTask> list = new ArrayList<>();
            for (Map.Entry<Long, UploadTask> entry : cacheMap.entrySet()) {
                UploadTask uploadTask = entry.getValue();
                if (uploadTask.getUserId().equals(userId)) {
                    list.add(entry.getValue());
                }
            }
            return list;
        }
    }

    /**
     * @description: 存储任务，建议优化成自动装配
     * @author: xukang
     * @create: 2025/8/5
     */
    public Long storageSave(UploadTask task) {
        if (task.getId() == null){ task.setId(new SnowflakeIdGenerator(1, 1).nextId());};

        if (StorageChannel.mysql.name().equals(storageChannel)) {
            // 保存到数据库

        } else if (StorageChannel.redis.name().equals(storageChannel)) {
            // 保存到redis

        } else {
            // 本地缓存
            uploadCache.put(task.getId(), task);
        }
        return task.getId();
    }


}
